import {computed, isRef, nextTick, ref, shallowRef, unref} from "vue";
import {showToast} from "./common.js";

export const defHandleThen = (res = {}, options = {}) => new Promise((resolve, reject) => {
  if (res.errCode === 0) {
    resolve(res)
    return
  }
  reject(res)
})

export const defHandleCatch = (err, options = {}) => new Promise((resolve, reject) => {
  reject(err)
})


export const useUniCloud = (options = {}, ...args) => {
  const {objName, funcName, impObjOpts = {}, customOpts = {}} = options
  const {customUI = true} = impObjOpts
  const { autoLog = import.meta.env.DEV, loading = ref(false), defData = null, immediate = false, toast = true, filter} = customOpts

  const data = isRef(defData) ? defData : ref(defData)
  const promise = shallowRef(null)

  const asyncFuncMap = uniCloud.importObject(objName, {customUI})

  const action = (params) => {

    loading.value = true

    let unRefArgs = args.map(item => unref(item))
    if (params) unRefArgs = [unref(params)]

    if(autoLog) console.log(`${objName}:${funcName}原始req`, JSON.parse(JSON.stringify(unRefArgs)))

    promise.value = new Promise((resolve, reject) => {
      asyncFuncMap[unref(funcName)](...unRefArgs).then(res => {

        if(autoLog) console.log(`${objName}:${funcName}原始res`, JSON.parse(JSON.stringify(res)))

        defHandleThen(res).then(res => {
          if (filter) res = filter(res)
          data.value = res.data
          loading.value = false
          resolve(res)
        }).catch((res) => {
          loading.value = false
          if (toast) showToast(res.errMsg)
          reject(res)
        })
      }).catch(err => {
        if(autoLog) console.log(`${objName}:${funcName}请求失败`, JSON.parse(JSON.stringify(err)))

        defHandleCatch(err, {toast}).catch(err => {
          loading.value = false
          if (toast) showToast(err.errMsg)
          reject(err)
        })
      })
    })
    return promise.value
  }

  if (immediate) action()

  return {
    loading,
    data,
    promise,
    action
  }

}


export const usePagerByCloud = (options = {}, params = {}) => {

  const pageNo = ref(1)
  const pageSize = ref(12)
  const pageList = ref([])
  const pageTotal = ref(Infinity)

  // 用于请求失败时回滚的页码
  let lastPageNo = unref(pageNo)

  const {loading, action} = useUniCloud({
    ...options,
    customOpts: {
      defData: ref([]),
      ...options.customOpts
    }
  }, computed(() => ({
    pageCurrent: unref(pageNo),
    pageSize: unref(pageSize),
    ...unref(params)
  })))

  const fetchPageList = () => {
    if (unref(loading)) return
    let promise = action()
    promise = promise.then(res => {
      pageList.value = pageList.value.concat(res.data)

      if (res.data?.length > 0) lastPageNo = pageNo.value
      else pageNo.value = lastPageNo

      if (res.total) pageTotal.value = res.total
      else if (res.data.length < unref(pageSize)) pageTotal.value = pageList.value.length

    }).catch(() => {
      pageNo.value = lastPageNo
    })
    return promise
  }

  const loadStatus = computed(() => {
    if (unref(loading)) return 'loading'
    if (unref(pageList).length < 1 && unref(pageNo) <= 1 && !unref(loading)) return 'no-more'
    if (unref(pageList).length >= unref(pageTotal) && (unref(pageNo) >= 1)) return 'no-more'
    return 'more'
  })

  const nextPage = () => {
    if (unref(loadStatus) === 'more') {
      ++pageNo.value
      fetchPageList()
    }
  }

  const rePageList = () => {
    pageList.value = []
    pageNo.value = 1
    fetchPageList()
  }

  onReachBottom(() => {
    if (unref(loading)) return
    nextPage()
  })

  return {
    pageNo,
    pageTotal,
    pageSize,
    pageList,
    loading,
    loadStatus,
    nextPage,
    fetchPageList,
    rePageList
  }
}
